package com.fsi.client;

import java.util.List;

import com.fsi.client.controller.Controller;
import com.fsi.client.controller.ControllerListener;
import com.fsi.client.event.CustomerInfoReturned;
import com.fsi.client.event.InformationRequested;
import com.fsi.client.event.ServiceFailed;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Anchor;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
import com.google.gwt.user.client.ui.VerticalPanel;

public class ApplicationGUI extends ServiceGUI implements
		ValueChangeHandler<String> {
	// TODO SHOW WAITING ICON
	// TODO LOAD CUSTOMER
	// TODO SHOW NO IMAGE ICON
	// TODO HISTORY
	// TODO LOGGING
	// TODO COUNTRY DROPDOWN CLASS
	// TODO REPORT PHOTO TOO BIG

	// ****** QUESTIONS ******

	protected static final String GETPHOTO = "photo";
	protected static final String HOME = "home";
	protected static final String LOGIN = "login";
	protected static final String OPTIONS = "option";
	protected static final String TEST = "test";
	protected static final String PERSONAL = "personal";
	protected static final String EDITCUSTOMER = "editcustomer";
	protected static final String NEWCUSTOMER = "newcustomer";
	protected static final String SHOWPHOTOS = "showphotos";

	// method constants
	protected static final int SHOWPERSONAL_METHOD = 0;
	protected static final int SHOWEDITCUSTOMER_METHOD = 1;
	protected static final int LOGINSUCCEED = 2;
	protected static final int SHOWPHOTOS_METHOD = 3;

	private final ScrollPanel sp = new ScrollPanel();
	private final VerticalPanel contentPanel = new VerticalPanel();
	private final HorizontalPanel headerPanel = new HorizontalPanel();
	private final Label headerLabel = new Label("Find Someone Interesting");
	private final HorizontalPanel centerPanel = new HorizontalPanel();
	private final VerticalPanel centerContentPanel = new VerticalPanel();
	private final VerticalPanel contentTopPanel = new VerticalPanel();

	// left panel
	private final VerticalPanel leftPanel = new VerticalPanel();
	protected final Button homeButton = new Button("Home");
	protected final Button personalButton = new Button("Personal");
	protected final Button editPersonalBtn = new Button("Edit Personal");
	protected final Button optionsButton = new Button("Options");
	protected final Button getPhotoButton = new Button("Get Photos");
	protected final Button testButton = new Button("Test");
	protected final Button loginButton = new Button("Log In/Out");
	protected final Button showPhotosButton = new Button("Show Photos");
	Button b = new Button("clear count");
	// footer
	private final VerticalPanel bottomPanel = new VerticalPanel();
	private final Label status = new Label();

	private final HorizontalPanel statusPanel = new HorizontalPanel();

	private VerticalPanel loginPanel;
	private final Label loginLabel = new Label(
			"Please sign in to your Google Account to access the StockWatcher application.");
	private final Anchor signInLink = new Anchor("Sign In");

	protected ApplicationServiceDelegate service;
	private TestGUI testGui;
	private PersonalGUI personalGui;
	private EditCustomerGUI editCustomerGui;
	private OptionsGUI optionsGui;
	private GetPhotoGUI photoGui;
	private ShowPhotosGUI showPhotosGui;
	private HomeGUI homeGui;
	private NewCustomerGUI newCustomerGui;

	ListBox debug = new ListBox();
	int i = 0;

	// fields
	protected List<Customer> customers;
	protected LoginInfo loginInfo = null;
	private String oldToken;
	private boolean dontReactToHistory = false;
	private final Controller controller = Application.getInstance()
			.getController();

	public ApplicationGUI() {

		personalButton.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				service.getCustomer(loginInfo.getEmailAddress(),
						new AsyncCallback<Customer>() {

							@Override
							public void onSuccess(Customer result) {
								controller.event(new CustomerInfoReturned(
										result));
							}

							@Override
							public void onFailure(Throwable caught) {
								controller.event(new ServiceFailed(caught));
							}
						});

			}
		});
		controller.addListener(CustomerInfoReturned.class,
				new ControllerListener<CustomerInfoReturned>() {

					@Override
					public void event(CustomerInfoReturned event) {
						Customer customer = event.getCustomer();
						personalGui.loadDetails(customer);
						setupVisibility(PERSONAL);
					}
				});

		buildTop();
		buildLeftPanel();
		buildCenterContent();
		buildBottom();

		centerPanel.add(leftPanel);
		centerPanel.add(centerContentPanel);

		contentTopPanel.add(headerPanel);
		contentTopPanel.add(centerPanel);

		sp.add(contentTopPanel);

		contentPanel.add(sp);
		contentPanel.add(bottomPanel);

		RootPanel.get("site").add(contentPanel);

		resize();

		contentTopPanel.setStyleName("contentTop");
		headerPanel.setStyleName("header");
		centerPanel.setStyleName("center");
		contentPanel.setStyleName("content");
		bottomPanel.setStyleName("bottom");
		RootPanel.get().setStyleName("root");

		wireEvents();

		Window.addResizeHandler(new ResizeHandler() {

			@Override
			public void onResize(ResizeEvent event) {
				resize();
			}

		});

		History.addValueChangeHandler(this);

		b.addClickHandler(new ClickHandler() {
			@Override
			public void onClick(ClickEvent event) {
				Application.getInstance().getController().event(
						new InformationRequested("dave"));
			}
		});

		Application.getInstance().getController().addListener(
				InformationRequested.class,
				new ControllerListener<InformationRequested>() {

					@Override
					public void event(InformationRequested event) {
						b.setText("clicked" + System.currentTimeMillis());
					}
				});

	}

	private void buildCenterContent() {
		// Assemble login panel.

		status.setText("Login required");
		loginPanel = new VerticalPanel();
		loginPanel.add(loginLabel);
		loginPanel.add(signInLink);
		loginPanel.setVisible(false);

		// assemble test
		homeGui = new HomeGUI();
		homeGui.setVisible(false);

		personalGui = new PersonalGUI();
		personalGui.setVisible(false);

		editCustomerGui = new EditCustomerGUI();
		editCustomerGui.setVisible(false);

		optionsGui = new OptionsGUI();
		optionsGui.setVisible(false);

		photoGui = new GetPhotoGUI();
		photoGui.setVisible(false);

		showPhotosGui = new ShowPhotosGUI();
		showPhotosGui.setVisible(false);

		testGui = new TestGUI();
		testGui.setVisible(false);

		newCustomerGui = new NewCustomerGUI();
		newCustomerGui.setVisible(false);

		centerContentPanel.add(debug);
		centerContentPanel.add(loginPanel);
		centerContentPanel.add(testGui);
		centerContentPanel.add(photoGui);
		centerContentPanel.add(showPhotosGui);
		centerContentPanel.add(optionsGui);
		centerContentPanel.add(personalGui);
		centerContentPanel.add(editCustomerGui);
		centerContentPanel.add(homeGui);
		centerContentPanel.add(newCustomerGui);

		debug.setVisibleItemCount(10);
		debug.setWidth("200px");
	}

	public void initGui() {
		ServiceGUI.service = this.service;
		ServiceGUI.gui = this;

		photoGui.gui = this;
		debug.clear();
		this.service.initLogIn();
	}

	private void buildBottom() {
		// statusPanel.setBorderWidth(2);
		// statusPanel.setWidth("100%");
		// statusPanel.add(status);
		bottomPanel.add(status);
		bottomPanel.setWidth("100%");
		bottomPanel.setBorderWidth(2);
	}

	private void buildTop() {
		headerLabel.setStyleName("headerLabel");
		headerPanel.add(headerLabel);
	}

	private void buildLeftPanel() {
		// setupButtonVisibility();
		homeButton.setStyleName("menuButton");
		personalButton.setStyleName("menuButton");
		editPersonalBtn.setStyleName("menuButton");
		optionsButton.setStyleName("menuButton");
		getPhotoButton.setStyleName("menuButton");
		showPhotosButton.setStyleName("menuButton");
		testButton.setStyleName("menuButton");
		loginButton.setStyleName("menuButton");
		leftPanel.add(homeButton);
		leftPanel.add(personalButton);
		leftPanel.add(editPersonalBtn);
		leftPanel.add(optionsButton);
		leftPanel.add(getPhotoButton);
		leftPanel.add(showPhotosButton);
		leftPanel.add(testButton);
		leftPanel.add(loginButton);
		// leftPanel.add(b);
		leftPanel.setStyleName("leftPanel");
	}

	protected void setupVisibility(String panelName) {
		try {
			loginPanel.setVisible(panelName == LOGIN);
			testGui.setVisible(panelName == TEST);
			personalGui.setVisible(panelName == PERSONAL);
			editCustomerGui.setVisible(panelName == EDITCUSTOMER);
			optionsGui.setVisible(panelName == OPTIONS);
			photoGui.setVisible(panelName == GETPHOTO);
			homeGui.setVisible(panelName == HOME);
			newCustomerGui.setVisible(panelName == NEWCUSTOMER);
			showPhotosGui.setVisible(panelName == SHOWPHOTOS);
		} catch (Exception e) {
			Window
					.alert("An error occurred in 'setupVisibilty': a form hasn't been instantiated");
			e.printStackTrace();
		}
	}

	// protected void setupButtonVisibility() {
	// homeButton.setVisible(customerExists);
	// personalButton.setVisible(customerExists);
	// optionsButton.setVisible(customerExists);
	// photoButton.setVisible(customerExists);
	//
	// }

	private void showLogin(boolean setDontReactToHistory) {
		if (setDontReactToHistory)
			dontReactToHistory = true;
		History.newItem(ApplicationGUI.LOGIN);
		signInLink.setHref(loginInfo.getLoginUrl());
		setupVisibility(LOGIN);
	}

	protected void showHome(boolean setDontReactToHistory) {
		if (setDontReactToHistory)
			dontReactToHistory = true;
		History.newItem(ApplicationGUI.HOME);
		setupVisibility(HOME);
	}

	public void showPersonal(boolean setDontReactToHistory) {
		if (setDontReactToHistory)
			dontReactToHistory = true;
		History.newItem(ApplicationGUI.PERSONAL);
		service.getCustomer(loginInfo.getEmailAddress(),
				ApplicationGUI.SHOWPERSONAL_METHOD);
	}

	public void showEditCustomer(boolean setDontReactToHistory) {
		if (setDontReactToHistory)
			dontReactToHistory = true;
		History.newItem(ApplicationGUI.EDITCUSTOMER);
		service.getCustomer(loginInfo.getEmailAddress(),
				SHOWEDITCUSTOMER_METHOD);
	}

	public void showTest(boolean setDontReactToHistory) {
		if (setDontReactToHistory)
			dontReactToHistory = true;
		History.newItem(ApplicationGUI.TEST);
		setupVisibility(TEST);
		testGui.resetNameBox();
		testGui.listCustomers();
	}

	public void showGetPhoto(boolean setDontReactToHistory) {
		if (setDontReactToHistory)
			dontReactToHistory = true;
		History.newItem(ApplicationGUI.GETPHOTO);
		gui.setupVisibility(GETPHOTO);
	}

	public void showPhotos(boolean setDontReactToHistory) {
		if (setDontReactToHistory)
			dontReactToHistory = true;
		History.newItem(ApplicationGUI.SHOWPHOTOS);
		service.getCustomer(loginInfo.getEmailAddress(),
				ApplicationGUI.SHOWPHOTOS_METHOD);
	};

	public void showOptions(boolean setDontReactToHistory) {
		if (setDontReactToHistory)
			dontReactToHistory = true;
		History.newItem(ApplicationGUI.OPTIONS);
		gui.setupVisibility(ApplicationGUI.OPTIONS);
	}

	public void showLoginOrLogout() {
		if (loginInfo.isLoggedIn()) {
			Window.Location.replace(loginInfo.getLogoutUrl());
		} else {
			showLogin(false);
		}

	}

	public void setStatus(String errorMsg) {
		status.setText(errorMsg);
	}

	// *******************************
	// ********* from service delegate
	// *******************************
	public void service_loginTestFailed(Throwable caught) {
		status.setText("Error on login: " + caught.getMessage());
		loginInfo = null;
	}

	public void service_loginTestSucceeded(LoginInfo loginInfo) {
		this.loginInfo = loginInfo;
		if (loginInfo.isLoggedIn()) {
			status.setText("Welcome " + loginInfo.getNickname());
			service.getCustomer(loginInfo.getEmailAddress(),
					ApplicationGUI.LOGINSUCCEED);
		} else {
			showLogin(false);
		}
	}

	public void afterLoginAndCustomer(Customer result) {
		if (result == null) {
			newCustomerGui.setLoginEmail(loginInfo.getEmailAddress());
			newCustomerGui.setEmail(loginInfo.getEmailAddress());
			setupVisibility(NEWCUSTOMER);
		} else {
			showHome(true);
			// String token = History.getToken();
			// System.out.println(token);
			// dontReactToHistory = false;
			// if (token.length() == 0) {
			// History.newItem(GWT.getHostPageBaseURL());
			// oldToken = "";
			// showHome(true);
			// } else {
			// History.newItem(token);
			// }

		}

	}

	public void service_showPhotos(Customer customer) {
		showPhotosGui.loadGui(customer.getLoginEmailAddress());
		setupVisibility(SHOWPHOTOS);
	}

	public void service_showPersonal(Customer customer) {
		personalGui.loadDetails(customer);
		setupVisibility(PERSONAL);
	}

	public void service_showEditCustomer(Customer customer) {
		editCustomerGui.loadDetails(customer);
		setupVisibility(EDITCUSTOMER);
	}

	@Override
	public void service_afterGetByEmailFailed() {
		newCustomerGui.setLoginEmail(loginInfo.getEmailAddress());
		newCustomerGui.setEmail(loginInfo.getEmailAddress());
		setupVisibility(NEWCUSTOMER);
	}

	// ********************************
	// ******************** WIRE EVENTS
	// ********************************
	private void wireEvents() {
		testGui.addButton.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				testGui.addNewCustomer();
			}
		});

		testGui.deleteCustomerButton.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				testGui.deleteCustomer();
			}
		});

		photoGui.uploadButton.addClickHandler(new ClickHandler() {

			@Override
			public void onClick(ClickEvent event) {
				photoGui.photo_upload();

			}
		});
	}

	@Override
	public void onValueChange(ValueChangeEvent<String> event) {
		if (dontReactToHistory) {
			dontReactToHistory = false;
			return;
		}
		if (oldToken != null && event.getValue().equals(oldToken))
			return;
		debug.addItem("old=" + oldToken);
		oldToken = event.getValue();
		debug.addItem("new=" + oldToken);

		if (event.getValue().equals(PERSONAL)) {
			service.getCustomer(loginInfo.getEmailAddress(),
					SHOWPERSONAL_METHOD);
		} else if (event.getValue().equals(HOME)) {
			showHome(false);
		} else if (event.getValue().equals(EDITCUSTOMER)) {
			showEditCustomer(false);
		} else if (event.getValue().equals(ApplicationGUI.GETPHOTO)) {
			showGetPhoto(false);
		} else if (event.getValue().equals(ApplicationGUI.LOGIN)) {
			showLogin(false);
		} else if (event.getValue().equals(ApplicationGUI.OPTIONS)) {
			showOptions(false);
		} else if (event.getValue().equals(ApplicationGUI.SHOWPHOTOS)) {
			showPhotos(false);
		} else if (event.getValue().equals(ApplicationGUI.TEST)) {
			showTest(false);
		} else if (event.getValue().equals(GETPHOTO)) {
			showGetPhoto(false);
		}

		// setupVisibility(oldToken);
		// debug.setText(event.getValue());
		// Window.alert(event.getValue());
	}

	private void resize() {
		sp.setHeight(Integer.toString(Window.getClientHeight() - 24) + "px");

	}

}
